import { Fly } from '@/effect/Fly';
import {
    Sky
} from '@/environment/Sky.js';
import { City } from '@/model/City';
import { loadManager } from '@/model/loadManager';
import { Ship } from '@/model/Ship';
import { modifySelectCityMaterial } from '@/shader/modifyCityMaterial';
import { ClickHandler } from '@/utils/clickHandler';
import { DataManager } from '@/utils/DataManager';
import { EffectManager } from '@/utils/EffectManager';
import {
    EventBus
} from '@/utils/EventBus';
import * as THREE from 'three';
import { OrbitControls } from 'three/examples/jsm/controls/OrbitControls';
import { CSS2DRenderer } from 'three/examples/jsm/renderers/CSS2DRenderer';
let scene, camera, renderer, control, css2Renderer;

// 初始化 3d 基本环境
function init() {
  scene = new THREE.Scene()
  camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 10000);
  camera.position.set(-148, 55, -101)

  // 创建渲染器
  renderer = new THREE.WebGLRenderer({ antialias: true })
  renderer.setSize(window.innerWidth, window.innerHeight)

  // 创建2D渲染器
  css2Renderer = new CSS2DRenderer()
  css2Renderer.setSize(window.innerWidth, window.innerHeight)
  css2Renderer.domElement.style.position = 'absolute'
  css2Renderer.domElement.style.top = '0px'
  css2Renderer.domElement.style.pointerEvents = 'none'

  // DOM 添加到页面
  const canvas = document.getElementById('canvas')
  canvas.appendChild(renderer.domElement)
  canvas.appendChild(css2Renderer.domElement)

  // 轨道控制器
  control = new OrbitControls(camera, renderer.domElement)
  control.update()

  // 坐标轴
  const axesHelper = new THREE.AxesHelper(1500)
  scene.add(axesHelper)

}

// 渲染循环
function renderLoop() {
  // 这里不再调用轨道控制器 update 方法，会影响摄像机 lookAt
  renderer.render(scene, camera)
  css2Renderer.render(scene, camera)

  // 遍历所有要做动效的物体执行里面的onTick方法
  EffectManager.getInstance().tickForEach()

  requestAnimationFrame(renderLoop)
}

// 灯光
function createLight() {
  // 基础光-环境光
  const ambientLight = new THREE.AmbientLight('#fff', 3)
  scene.add(ambientLight)
}

// 适配
window.addEventListener('resize', function () {
  camera.aspect = window.innerWidth / window.innerHeight;
  camera.updateProjectionMatrix();
  renderer.setSize(window.innerWidth, window.innerHeight);
  css2Renderer.setSize(window.innerWidth, window.innerHeight);
})

// 启动
window.addEventListener('DOMContentLoaded', function () {
  init()
  createLight()

  // 监听点击事件对应光线投影
  ClickHandler.getInstance().init(camera)

  new Sky(scene).setBack('/textures/sky/', [
    'px.jpg',
    'nx.jpg',
    'py.jpg',
    'ny.jpg',
    'pz.jpg',
    'nz.jpg',
  ])

  // 导入城市和游船
  let ship;
  loadManager(['fbx/city.fbx', 'gltf/ship.glb'], async (modeList) => {
    try {
        modeList.forEach(async obj => {
            if (obj.url === 'fbx/city.fbx') {
                const city = new City(obj.model, scene, camera, control)
                const { data } = await new DataManager().getData()
                city.dataObj = data.buildingsIntroduce
                city.lastOriginMat = [] // 上一次高亮物体本来的材质
                EventBus.getInstance().on('pieClick', (buildName) => {
                    // 如果之前有点击的dom，给他恢复一下
                    let index = 0
                    if (city.lastClick && city.lastOriginMat.length > 0) {
                        city.lastClick.traverse(model => {
                            model.material = city.lastOriginMat[index++]
                        })
                    }
                    // 给最新的模型设置边框线
                    let targetBuild = city.model.getObjectByName(buildName)
                    targetBuild.traverse((model) => {
                        if (model.type === 'Mesh') {
                            city.lastOriginMat.push(model.material)
                            model.material = new THREE.MeshBasicMaterial({
                                color: 0x0000ff
                            })
                            modifySelectCityMaterial(model)
                        }
                    })
                    city.lastClick = targetBuild
                })

                // 初始化执行一次
                city.initFire(data.fireBuilding.name)

                EventBus.getInstance().on('refreshHomeCount', (data) => {
                    let buildName = data.data.fireBuilding.name
                    if (buildName) {
                        city.initFire(buildName)
                    }
                })
            } else if (obj.url === 'gltf/ship.glb') {
                ship = new Ship(obj.model, scene, camera, control)
                ship.model.position.set(150, 0, -80)
                ship.model.rotation.set(0, - Math.PI / 2, 0)
                ship.model.scale.set(100, 100, 100)
                EffectManager.getInstance().addObj(ship)
            }
        })

        // 更新图表的数据
        DataManager.getInstance().refreshData()
    } catch (error) {
       console.log(error, 'error');
    }
  })

  let flyGeo = new THREE.BoxGeometry(5, 5, 5)
  let material = new THREE.MeshBasicMaterial({
    color: 'lightblue',
    side: THREE.DoubleSide,
  })
  let flyMesh = new THREE.Mesh(flyGeo, material)
  flyMesh.visible = false
  const fly = new Fly(flyMesh, scene, camera, control)
  // 添加动效
  EffectManager.getInstance().addObj(fly)
  // 注册事件，控制摄像机是否鸟瞰
  EventBus.getInstance().on('mode-topView', (isOpen) => {
    // 避免轨道控制器发生抖动
    fly.control.enabled = !isOpen
    // 控制摄像机的鸟瞰开启于关闭
    fly.isCameraMove = isOpen
  })

  // 避免物体的轨道控制器发生抖动
  EventBus.getInstance().on('mode-roaming', (isOpen) => {
    // 这里不能让轮船的轨道控制器发生抖动
    ship.control.enabled = !isOpen
    ship.isMoveCamera = isOpen
  })

  


  renderLoop()
})

